#include"Index.h"

void Initialize(BWT* bwt, unsigned int bwtLength)
{
	bwt->textLength = bwtLength;
	bwt->occSizeInWord = BWTOccValueMinorSizeInWord(bwt->textLength);
	bwt->occMajorSizeInWord = BWTOccValueMajorSizeInWord(bwt->textLength);
#if LAYER_INDEX_2
	bwt->occValue = new unsigned int[bwt->occSizeInWord + 4];
	bwt->occMajorValue = new unsigned int[bwt->occMajorSizeInWord + 4];	
#endif
}

void LoadLookupTable(LookupTable *lookupTable, const char * fileName, const int mtableSize)  {

	lookupTable->tableSize = mtableSize;
	unsigned long long NR_TOP = 1 << (lookupTable->tableSize * 2);
	lookupTable->table = (unsigned int *)malloc(sizeof(unsigned) * NR_TOP);

	FILE * fin = fopen(fileName, "rb");
	unsigned step = 1048576;
	unsigned int i;
	for (i = 0; i < NR_TOP; i += step) {
		fread(lookupTable->table + i, sizeof(*(lookupTable->table)), step, fin);
	}
	fclose(fin);
}

void BuildOccCountMap(unsigned int *occCountMap)
{
	unsigned int i,j, temp, num;
	
	for(i=0; i<COUNT_MAP_SIZE;i++)
		for(j=0; j<ALPHABET_SIZE; j++)
			occCountMap[j * COUNT_MAP_SIZE + i] = 0;
	for(i=0; i<COUNT_MAP_SIZE; i++)
	{
		temp = i;
		for(j=0; j<8; j++){
			num = temp & 0x3;
			temp = temp >> 2;
			occCountMap[num * COUNT_MAP_SIZE + i]++;
		}
	}

}

void BuildDeviceOccCountMap(char * occCountMap)
{
        unsigned int i,j, temp;
	char num;

        for(i=0; i<DEVICE_COUNT_MAP_SIZE;i++)
                for(j=0; j<ALPHABET_SIZE; j++)
                        occCountMap[j * DEVICE_COUNT_MAP_SIZE + i] = 0;
        for(i=0; i<DEVICE_COUNT_MAP_SIZE; i++)
        {
                temp = i;
                for(j=0; j<4; j++){
                        num = temp & 0x3;
                        temp = temp >> 2;
                        occCountMap[num * DEVICE_COUNT_MAP_SIZE + i] += 1;
                }
        }	
}

void getSaValue(BWT *bwt, unsigned int left, unsigned int right, unsigned int * saInterval)
{
	unsigned int i;
	for (i=left; i<=right; i++)
	{
		//	bwt->saInterval[i-left] = bwt->saValue[i];
	}
}


void DecodeBWT(BWT *bwt, unsigned int * tempBwtCode)
{
	//	int i,j,k;
	bwt->bwtCode = tempBwtCode;
}

unsigned int BWTResidentSizeInWord(const unsigned int numChar) {

	unsigned int numCharRoundUpToOccInterval;

	// The $ in BWT at the position of inverseSa0 is not encoded
	numCharRoundUpToOccInterval = (numChar + OCC_MINOR_INTERVAL - 1) / OCC_MINOR_INTERVAL * OCC_MINOR_INTERVAL;

	return (numCharRoundUpToOccInterval + CHAR_PER_WORD - 1) / CHAR_PER_WORD;

}

unsigned int BWTFileSizeInWord(const unsigned int numChar) {

	// The $ in BWT at the position of inverseSa0 is not encoded
	return (numChar + CHAR_PER_WORD - 1) / CHAR_PER_WORD;

}

unsigned int BWTOccValueMinorSizeInWord(const unsigned int numChar) {

	unsigned int numOfOccValue;

	numOfOccValue = (numChar + OCC_MINOR_INTERVAL - 1) / OCC_MINOR_INTERVAL + 1;							// Value at both end for bi-directional encoding
	return (numOfOccValue + OCC_VALUE_PER_WORD - 1) / OCC_VALUE_PER_WORD * ALPHABET_SIZE;

}

unsigned int BWTOccValueMajorSizeInWord(const unsigned int numChar) {

	unsigned int numOfOccValue;
	unsigned int numOfOccIntervalPerMajor;

	numOfOccValue = (numChar + OCC_MINOR_INTERVAL - 1) / OCC_MINOR_INTERVAL + 1;                                // Value at both end for bi-directional encoding
	numOfOccIntervalPerMajor = OCC_MAJOR_INTERVAL / OCC_MINOR_INTERVAL;

	return (numOfOccValue + numOfOccIntervalPerMajor - 1) / numOfOccIntervalPerMajor * ALPHABET_SIZE;

}


void BWTClearTrailingBwtCode(BWT *bwt) {

	unsigned int bwtResidentSizeInWord;
	unsigned int wordIndex, offset;
	unsigned int i;
	unsigned int textLength = bwt->textLength;

	bwtResidentSizeInWord = BWTResidentSizeInWord(textLength);

	wordIndex = textLength / CHAR_PER_WORD;
	offset = (textLength - wordIndex * CHAR_PER_WORD) * BIT_PER_CHAR;
	if (offset > 0) {
		//		printf("offset:  %d\n", offset);
		bwt->bwtCode[wordIndex] = truncateRight(bwt->bwtCode[wordIndex], BITS_IN_WORD - offset);
	} else 	if (wordIndex < bwtResidentSizeInWord) {
		bwt->bwtCode[wordIndex] = 0;
	}
	

	for (i=wordIndex+1; i<bwtResidentSizeInWord; i++) {
		bwt->bwtCode[i] = 0;
		//		printf( "bwtCode[%d] = 0\n", i);
	}
}

